#include "MegaClipboardModel.h"
#include "MegaClipboardModel_p.h"

#include <QtGui/QApplication>
#include <QtCore/QByteArray>
#include <QtGui/QClipboard>
#include <QtCore/QHash>
#include <QtCore/QMimeData>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QVariant>

#include <QtDebug>

// Private class realization

MegaClipboardModelPrivate::MegaClipboardModelPrivate()
	: m_clipboard(qApp->clipboard())
	, clipboardManualUpdate(false)
{
}

MegaClipboardModelPrivate::~MegaClipboardModelPrivate()
{
	qDeleteAll(m_items);
	m_items.clear();
}

void MegaClipboardModelPrivate::init()
{
	Q_Q(MegaClipboardModel);
	_q_updateClipboard();
	QObject::connect(m_clipboard, SIGNAL(dataChanged()), q, SLOT(_q_updateClipboard()));
}

int MegaClipboardModelPrivate::rowCount(const QModelIndex & _parent) const
{
	Q_UNUSED(_parent);
	return m_items.count();
}

QVariant MegaClipboardModelPrivate::data(const QModelIndex & _index, int _role) const
{
	QVariant returnValue;
	if (_index.isValid())
	{
		ClipData * currentItem = m_items[_index.row()];
		if (_role == MegaClipboardModel::ClipCaptionRole)
		{
			returnValue = currentItem->text();
		}
		else if (_role == MegaClipboardModel::ClipDataRole)
		{
			if (currentItem->hasHtml())
				returnValue = currentItem->html();
			else if (currentItem->hasText())
				returnValue = currentItem->text();
			else if (currentItem->hasImage())
				returnValue = currentItem->imageData();
		}
	}
	return returnValue;
}

bool MegaClipboardModelPrivate::removeRows(int _row, int _count, const QModelIndex & _parent)
{
	Q_Q(MegaClipboardModel);

	// precondition check for debug
	Q_ASSERT_X(_row >= 0 && _row < m_items.size(), "removing rows", "index is out of range");

	if (_row >= 0 && _row < m_items.size())
	{
		q->beginRemoveRows(_parent, _row, _row + _count - 1);
		delete m_items.takeAt(_row);
		q->endRemoveRows();
		return true;
	}
	else
		return false;
}

bool MegaClipboardModelPrivate::activate(int _index)
{
	Q_Q(MegaClipboardModel);

//	if (!_index.isValid())
//		return false;

	int row = _index;//.row();
	// precondition check for debug
	Q_ASSERT_X(row >= 0 && row < m_items.size(), "activate item", "index is out of range");

	if (row >= 0 && row < m_items.size())
	{
		qWarning() << "Activate" << row;
		if (!q->beginMoveRows(QModelIndex(), row, row, QModelIndex(), 0))
			return false;
		m_items.move(row, 0);
		q->endMoveRows();

		clipboardManualUpdate = true;
		m_clipboard->setMimeData(m_items[row]);
		return true;
	}
	else
		return false;
}

void MegaClipboardModelPrivate::_q_updateClipboard()
{
	// If clipboard update was initiated by us
	if (clipboardManualUpdate)
	{
		clipboardManualUpdate = false;
		return;
	}

	Q_Q(MegaClipboardModel);

	ClipData * newItem = new ClipData;
	foreach (QString mime, m_clipboard->mimeData()->formats())
	{
		newItem->setData(mime, m_clipboard->mimeData()->data(mime));
	}

	q->beginInsertRows(QModelIndex(), m_items.count(), m_items.count());
	m_items.append(newItem);
	q->endInsertRows();
}


// public class realization

MegaClipboardModel::MegaClipboardModel(QObject *parent)
	: QAbstractListModel(parent)
	, d_ptr(new MegaClipboardModelPrivate)
{
	QHash<int, QByteArray> roles;
	roles[ClipCaptionRole] = "clipText";
	roles[ClipDataRole] = "clipData";
	setRoleNames(roles);

	Q_D(MegaClipboardModel);
	d->q_ptr = this;
	d->init();
}

MegaClipboardModel::~MegaClipboardModel()
{
	Q_D(MegaClipboardModel);
	delete d;
}


int MegaClipboardModel::rowCount(const QModelIndex & _parent) const
{
	Q_D(const MegaClipboardModel);
	return d->rowCount(_parent);
}

QVariant MegaClipboardModel::data(const QModelIndex & _index, int _role) const
{
	Q_D(const MegaClipboardModel);
	return d->data(_index, _role);
}

QVariant MegaClipboardModel::headerData(int _section, Qt::Orientation _orientation, int _role) const
{
	Q_UNUSED(_section);
	Q_UNUSED(_orientation);
	Q_UNUSED(_role);

	return QVariant();
}

bool MegaClipboardModel::removeRows(int _row, int _count, const QModelIndex & _parent)
{
	Q_D(MegaClipboardModel);
	return d->removeRows(_row, _count, _parent);
}

bool MegaClipboardModel::activate(int _index)
{
	Q_D(MegaClipboardModel);
	return d->activate(_index);
}

#include "moc_MegaClipboardModel.cpp"
